<template>
  <div class="voice-recorder">
    <h2>语音转写 · 情感与逻辑识别</h2>
    <div class="control-panel">
      <button @click="toggleRecording">{{ buttonText }}</button>
    </div>

    <div class="result-panel" v-html="formattedResult"></div>

    <div v-if="analysisResult" class="analysis-panel">
      <h3>🎯 识别文本：</h3>
      <p>{{ analysisResult.text }}</p>

      <h3>情感分析：</h3>
      <pre>{{ JSON.stringify(analysisResult.sentiment, null, 2) }}</pre>

      <h3>逻辑判断：</h3>
      <p><strong>相似度：</strong>{{ (analysisResult.logic.similarity * 100).toFixed(2) }}%</p>
      <p :style="{ color: analysisResult.logic.flag ? 'red' : 'green' }">
        {{ analysisResult.logic.flag ? '⚠️ ' + analysisResult.logic.message : '✅ ' + (analysisResult.logic.message || '未检测到明显逻辑矛盾。') }}
      </p>
    </div>
  </div>
</template>

<script>
import RecorderManager from 'recorder-manager'; // 假设你有这个录音库
import CryptoJS from 'crypto-js';

export default {
  data() {
    return {
      APPID: 'e9f15e7b',
      API_KEY: '93c94a284b6888c5807546666e22253e',
      recorder: null,
      asrWebSocket: null,
      analysisWebSocket: null,
      analysisWSConnected: false,
      recognitionResult: '',
      tempResult: '',
      isRecording: false,
      isLoading: false,
      connectionStatus: 'CLOSED',
      analysisResult: null,
    };
  },
  computed: {
    buttonText() {
      if (this.connectionStatus === 'CONNECTING') return '建立连接中...';
      if (this.connectionStatus === 'OPEN') return '录音中...';
      return '开始录音';
    },
    formattedResult() {
      return (this.recognitionResult || '') + (this.tempResult ? `<span class="temp">${this.tempResult}</span>` : '');
    },
  },
  mounted() {
    this.initRecorder();
    this.initAnalysisWebSocket();
  },
  beforeDestroy() {
    this.disconnect();
    this.cleanupAnalysisWS();
  },
  methods: {
    initRecorder() {
      this.recorder = new RecorderManager('/dist');
      this.recorder.onStart = () => {
        this.isRecording = true;
        this.connectionStatus = 'OPEN';
      };
      this.recorder.onStop = () => {
        this.isRecording = false;
      };
      this.recorder.onFrameRecorded = ({ isLastFrame, frameBuffer }) => {
        if (this.asrWebSocket && this.asrWebSocket.readyState === WebSocket.OPEN) {
          this.asrWebSocket.send(new Int8Array(frameBuffer));
          if (isLastFrame) this.asrWebSocket.send(JSON.stringify({ end: true }));
        }
      };
    },
    getAsrUrl() {
      const ts = Math.floor(Date.now() / 1000);
      const signa = CryptoJS.MD5(this.APPID + ts).toString();
      const signature = CryptoJS.HmacSHA1(signa, this.API_KEY).toString(CryptoJS.enc.Base64);
      return `wss://rtasr.xfyun.cn/v1/ws?appid=${this.APPID}&ts=${ts}&signa=${encodeURIComponent(signature)}`;
    },
    connect() {
      this.isLoading = true;
      this.connectionStatus = 'CONNECTING';
      this.recognitionResult = '';
      this.tempResult = '';
      this.analysisResult = null;

      // 建立ASR连接
      this.asrWebSocket = new WebSocket(this.getAsrUrl());
      this.asrWebSocket.binaryType = 'arraybuffer';

      this.asrWebSocket.onopen = () => {
        this.isLoading = false;
        this.recorder.start({ sampleRate: 16000, frameSize: 1280 });
      };
      this.asrWebSocket.onmessage = e => this.handleAsrMessage(e.data);
      this.asrWebSocket.onerror = () => {
        this.recognitionResult += `<p class="error">ASR 连接错误，请重试</p>`;
        this.disconnect();
      };
      this.asrWebSocket.onclose = () => this.disconnect();
    },
    disconnect() {
      this.isRecording = false;
      this.isLoading = false;
      this.connectionStatus = 'CLOSED';
      this.recorder.stop();
      if (this.asrWebSocket) this.asrWebSocket.close();
      this.asrWebSocket = null;
    },
    handleAsrMessage(msg) {
    console.log("收到ASR消息：", msg);
    const j = JSON.parse(msg);
    if (j.action === 'result') {
      const dt = JSON.parse(j.data);
      console.log("ASR解析数据：", dt);
      console.log("dt.cn.st.type =", dt.cn.st.type);
      let text = '';
      dt.cn.st.rt.forEach(rt =>
        rt.ws.forEach(ws =>
          ws.cw.forEach(c => (text += c.w))
        )
      );
      if (dt.cn.st.type == 0) {
        this.recognitionResult += text;
        this.tempResult = '';
        console.log("发送文本给分析服务:", this.recognitionResult);
        this.sendTextForAnalysis(this.recognitionResult);
      } else {
        this.tempResult = text;
      }
    }
    },

    // 分析WebSocket相关
    initAnalysisWebSocket() {
      this.analysisWebSocket = new WebSocket("ws://121.43.49.125:8000/ws/asr_emotion_logic");
      this.analysisWebSocket.onopen = () => {
        this.analysisWSConnected = true;
        console.log("分析 WebSocket 已连接");
      };
      this.analysisWebSocket.onmessage = e => {
        try {
          this.analysisResult = JSON.parse(e.data);
          console.log("分析结果：", this.analysisResult);
        } catch {
          this.analysisResult = {
            text: '',
            sentiment: '解析失败',
            logic: { similarity: 0, flag: false, message: '返回异常' },
          };
        }
      };
      this.analysisWebSocket.onerror = () => {
        this.analysisResult = {
          text: '',
          sentiment: '分析服务失败',
          logic: { similarity: 0, flag: false, message: '' },
        };
      };
      this.analysisWebSocket.onclose = () => {
        this.analysisWSConnected = false;
        console.log("分析 WebSocket 已关闭");
      };
    },

    sendTextForAnalysis(text) {
      if (this.analysisWSConnected && this.analysisWebSocket.readyState === WebSocket.OPEN) {
        this.analysisWebSocket.send(JSON.stringify({ text }));
        console.log("发送文本给分析服务:", text);
      } else {
        console.warn("分析 WebSocket 未连接，无法发送文本");
      }
    },

    cleanupAnalysisWS() {
      if (this.analysisWebSocket && this.analysisWebSocket.readyState === WebSocket.OPEN) {
        this.analysisWebSocket.close();
      }
      this.analysisWebSocket = null;
      this.analysisWSConnected = false;
    },

    toggleRecording() {
      if (this.connectionStatus === 'CLOSED') {
        this.connect();
      } else {
        this.disconnect();
      }
    },
  },
};
</script>

<style scoped>
.voice-recorder {
  max-width: 800px;
  margin: 20px auto;
  padding: 15px;
  font-family: Arial;
}
.control-panel {
  margin-bottom: 20px;
}
.result-panel {
  min-height: 150px;
  padding: 15px;
  border: 1px solid #ddd;
  background: #f9f9f9;
  line-height: 1.6;
}
.temp {
  color: #777;
}
.error {
  color: red;
}
.analysis-panel {
  margin-top: 20px;
  padding: 15px;
  border-top: 2px solid #888;
  background: #f1f1f1;
}
</style>
